package com.changpei.core.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.*;
import com.aliyuncs.AcsResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.RpcAcsRequest;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.facebody.model.v20191230.DetectCelebrityRequest;
import com.aliyuncs.facebody.model.v20191230.DetectCelebrityResponse;
import com.aliyuncs.imageaudit.model.v20191230.ScanImageRequest;
import com.aliyuncs.imageaudit.model.v20191230.ScanImageRequest.Task;
import com.aliyuncs.imageaudit.model.v20191230.ScanImageResponse;
import com.aliyuncs.imageaudit.model.v20191230.ScanTextRequest;
import com.aliyuncs.imageaudit.model.v20191230.ScanTextRequest.Labels;
import com.aliyuncs.imageaudit.model.v20191230.ScanTextRequest.Tasks;
import com.aliyuncs.imageaudit.model.v20191230.ScanTextResponse;
import com.aliyuncs.imagerecog.model.v20190930.*;
import com.aliyuncs.profile.DefaultProfile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 *
 *
 * @author Way on 2021/8/11
 */
@Component
@SuppressWarnings("all")
public class AliYunOssUtil {

    @Autowired
    private AliYunConfig aliYunConfig;

    @Autowired
    private CoreConfig coreConfig;

    /**
     * 将文件上传至oss
     * @param fileName
     * @param fileFolder
     * @return
     */
    public String upload(String fileName, String fileFolder) {
        OSS ossClient = new OSSClientBuilder()
                .build(aliYunConfig.getEndpoint(), aliYunConfig.getAccessKeyId(), aliYunConfig.getAccessKeySecret());

        // 创建PutObjectRequest对象。
        PutObjectRequest putObjectRequest = new PutObjectRequest(aliYunConfig.getBucketName(), fileFolder + "/" + fileName, new File(coreConfig.getUploadPath() + fileName));
        // 如果需要上传时设置存储类型与访问权限，请参考以下示例代码。
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
        metadata.setObjectAcl(CannedAccessControlList.PublicRead);
        putObjectRequest.setMetadata(metadata);

        // 上传文件。
        PutObjectResult putObjectResult = ossClient.putObject(putObjectRequest);

        // 关闭OSSClient。
        ossClient.shutdown();

        if (!ObjectUtils.isEmpty(putObjectResult)) {
            return putObjectResult.getETag();
        }

        return null;
    }

    /**
     * 通用图像打标
     *
     * @param file
     * @throws Exception
     */
    public JSONArray taggingImage(String file) throws Exception {
        System.out.println("--------  通用图像打标 --------------");
        TaggingImageRequest req = new TaggingImageRequest();
        // 注意：下面的链接换成自有的oss链接
        req.setImageURL(file);
        TaggingImageResponse resp = getAcsResponse(req);
        return JSON.parseArray(JSON.toJSONString(resp.getData().getTags()));
    }

    /**
     * 场景识别
     *
     * @param file
     * @throws Exception
     */
    public void recognizeScene(String file) throws Exception {
        System.out.println("--------  场景识别 --------------");
        RecognizeSceneRequest req = new RecognizeSceneRequest();
        // 注意：下面的链接换成自有的oss链接
        req.setImageURL(file);
        RecognizeSceneResponse resp = getAcsResponse(req);
        printResponse(req.getSysActionName(), resp.getRequestId(), resp);
    }

    /**
     * 风格识别
     * @param file
     * @throws Exception
     */
    public void recognizeImageStyle(String file) throws Exception {
        RecognizeImageStyleRequest req = new RecognizeImageStyleRequest();
        System.out.print("--------  风格识别 ----");
        req.setUrl(file);
        RecognizeImageStyleResponse resp = getAcsResponse(req);
        printResponse(req.getSysActionName(), resp.getRequestId(), resp);
    }

    /**
     * 内容审核 -> 图片审核
     * @param file
     * @throws Exception
     * @return
     */
    public boolean scanImage(String file) throws Exception {
        System.out.println("--------  内容审核 --------------");
        ScanImageRequest req = new ScanImageRequest();
        req.setScenes(aliYunConfig.getImagesFilter());

        List<Task> taskList = new ArrayList<>();
        Task task = new Task();

        task.setDataId(UUID.randomUUID().toString());
        task.setImageURL(file);
        taskList.add(task);
        req.setTasks(taskList);
        ScanImageResponse resp = getAcsResponse(req);
        String pass = "pass";
        for (ScanImageResponse.Data.Result result : resp.getData().getResults()) {
            for (ScanImageResponse.Data.Result.SubResult subResult : result.getSubResults()) {
                if (!pass.equals(subResult.getSuggestion())) {
                    return false;
                }
            }
        }
        return true;
    }

    /**
     * 内容审核 -> 文本审核
     * @param text
     * @throws Exception
     * @return
     */
    public boolean scanText(String text) throws Exception {
        ScanTextRequest req = new ScanTextRequest();

        List<Tasks> tasksList = new ArrayList<>();

        Tasks tasks = new Tasks();
        tasks.setContent(text);
        tasksList.add(tasks);
        req.setTaskss(tasksList);

        List<String> filter = aliYunConfig.getTextFilter();

        List<Labels> labelsList = filter.stream().map(s -> {
            Labels labels = new Labels();
            labels.setLabel(s);
            return labels;
        }).collect(Collectors.toList());

        req.setLabelss(labelsList);

        String pass = "pass";
        ScanTextResponse resp = getAcsResponse(req);
        for (ScanTextResponse.Data.Element element : resp.getData().getElements()) {
            for (ScanTextResponse.Data.Element.Result result : element.getResults()) {
                if (pass.equals(result.getSuggestion())) {
                    return true;
                }
            }
        }

        return false;
    }

    /**
     * 明星识别
     * @param file
     * @throws Exception
     */
    public void detectCelebrity(String file) throws Exception {
        DetectCelebrityRequest req = new DetectCelebrityRequest();
        req.setImageURL(file);
        DetectCelebrityResponse resp = getAcsResponse(req);
        printResponse(req.getSysActionName(), resp.getRequestId(), resp);
    }

    /**
     * 发送请求
     *
     * @param req
     * @param <R>
     * @param <T>
     * @return
     * @throws Exception
     */
    private <R extends RpcAcsRequest<T>, T extends AcsResponse> T getAcsResponse(R req) throws Exception {
        DefaultProfile profile = DefaultProfile.getProfile(aliYunConfig.getRegionId(), aliYunConfig.getAccessKeyId(), aliYunConfig.getAccessKeySecret());
        IAcsClient client = new DefaultAcsClient(profile);
        try {
            return client.getAcsResponse(req);
        } catch (ServerException e) {
            // 服务端异常
            System.out.printf("ServerException: errCode=%s, errMsg=%s%n", e.getErrCode(), e.getErrMsg());
            throw e;
        } catch (ClientException e) {
            // 客户端错误
            System.out.printf("ClientException: errCode=%s, errMsg=%s%n", e.getErrCode(), e.getErrMsg());
            throw e;
        } catch (Exception e) {
            System.out.println("Exception:" + e.getMessage());
            throw e;
        }
    }

    public static void printResponse(String actionName, String requestId, AcsResponse data) {
        System.out.printf("actionName=%s, requestId=%s, data=%s%n", actionName, requestId,
                JSON.toJSONString(data));
    }
}
